package com.wxy.favorites.service;

import cn.hutool.core.util.StrUtil;
import com.wxy.favorites.constant.EmailConstants;
import com.wxy.favorites.constant.LogConstants;
import com.wxy.favorites.core.ApiResponse;
import com.wxy.favorites.core.NoRollbackException;
import com.wxy.favorites.core.PageInfo;
import com.wxy.favorites.dao.FeedbackRepository;
import com.wxy.favorites.dao.SystemLogRepository;
import com.wxy.favorites.dao.UserRepository;
import com.wxy.favorites.dto.SendFeedbackDto;
import com.wxy.favorites.entity.Feedback;
import com.wxy.favorites.entity.SystemLog;
import com.wxy.favorites.entity.User;
import com.wxy.favorites.security.ContextUtils;
import com.wxy.favorites.security.SecurityUser;
import com.wxy.favorites.util.AssertUtils;
import com.wxy.favorites.util.EmailUtils;
import com.wxy.favorites.util.IpUtils;
import com.wxy.favorites.util.SqlUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @Author wangxiaoyuan
 * @Date 2020/4/24 11:50
 * @Description
 **/
@Slf4j
@Service
@Transactional(noRollbackFor = NoRollbackException.class)
public class FeedbackService {

    @Autowired
    private FeedbackRepository feedbackRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private EmailUtils emailUtils;

    @Autowired
    private SystemLogRepository systemLogRepository;

    public Feedback save(Feedback feedback) {
        feedback.setCreateTime(new Date());
        return feedbackRepository.save(feedback);
    }

    public PageInfo<Feedback> findPage(String account, String content, Integer isRead, Integer pageNum, Integer pageSize) {
        String text = SqlUtils.trimAndEscape(content);
        List<Sort.Order> orders = new ArrayList<>();
        orders.add(new Sort.Order(Sort.Direction.DESC, "createTime"));
        Pageable pageable = PageRequest.of(pageNum - 1, pageSize, Sort.by(orders));
        // 构造自定义查询条件
        Specification<Feedback> queryCondition = (root, criteriaQuery, criteriaBuilder) -> {
            List<Predicate> predicateList = new ArrayList<>();
            if (StrUtil.isNotBlank(text)) {
                predicateList.add(criteriaBuilder.like(root.get("content"), "%" + text + "%"));
            }
            if (StrUtil.isNotBlank(account)) {
                predicateList.add(criteriaBuilder.equal(root.get("account"), account));
            }
            if (isRead != null) {
                predicateList.add(criteriaBuilder.equal(root.get("isRead"), isRead));
            }
            return criteriaBuilder.and(predicateList.toArray(new Predicate[0]));
        };
        Page<Feedback> page = feedbackRepository.findAll(queryCondition, pageable);
        return new PageInfo<>(page.getContent(), page.getTotalPages(), page.getTotalElements());
    }

    public Feedback findById(Integer id) {
        return feedbackRepository.findById(id).orElse(null);
    }

    public Feedback findRecentByAccount(String account) {
        return feedbackRepository.findTopByAccountOrderByCreateTimeDesc(account);
    }

    public void deleteById(Integer id) {
        feedbackRepository.deleteById(id);
    }

    public Feedback update(Feedback feedback) {
        return feedbackRepository.save(feedback);
    }

    public Integer read(Integer id) {
        Feedback feedback = feedbackRepository.findById(id).orElse(null);
        AssertUtils.notNull(feedback, "反馈不存在");
        AssertUtils.isTrue(Objects.equals(feedback.getIsRead(), 0), "反馈已被查阅");
        feedback.setIsRead(1);
        feedbackRepository.save(feedback);
        return feedback.getIsRead();
    }

    public Boolean delete(Integer id) {
        Feedback feedback = feedbackRepository.findById(id).orElse(null);
        AssertUtils.notNull(feedback, "反馈不存在");
        feedbackRepository.deleteById(id);
        SecurityUser currentUser = ContextUtils.getCurrentUser();
        systemLogRepository.save(new SystemLog().setCreateTime(new Date()).setIp(IpUtils.getIp()).setContent(String.format(LogConstants.FEEDBACK_DELETE_MSG, currentUser.getUsername(), feedback.getAccount(), feedback.getContent(), feedback.getRemark())));
        return true;
    }

    public Boolean notice(SendFeedbackDto dto) {
        Feedback feedback = feedbackRepository.findById(dto.getId()).orElse(null);
        AssertUtils.notNull(feedback, "反馈不存在");
        feedback.setIsRead(2);
        feedback.setRemark(dto.getContent());
        feedbackRepository.save(feedback);
        User user = userRepository.findByUsername(feedback.getAccount());
        String email = user.getEmail();
        emailUtils.sendHtmlMail(email, EmailConstants.ADMIN_FEEDBACK_TITLE, dto.getContent().replaceAll("\n", "<br>"));
        SecurityUser currentUser = ContextUtils.getCurrentUser();
        systemLogRepository.save(new SystemLog().setCreateTime(new Date()).setIp(IpUtils.getIp()).setContent(String.format(LogConstants.FEEDBACK_SEND_MSG, currentUser.getUsername(), user.getUsername(), feedback.getContent(), dto.getContent())));
        return true;
    }
}

